﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Devonline.AspNetCore;

/// <summary>
/// 基于 DataService 的数据增删改查带导出数据到 excel 的基础控制器
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
/// <typeparam name="TEntitySet">业务数据类型</typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
[Authorize]
[ApiController]
public abstract class DataExportServiceController<TDbContext, TEntitySet, TKey>(
    ILogger<DataExportServiceController<TDbContext, TEntitySet, TKey>> logger,
    IDataService<TDbContext, TEntitySet, TKey> dataService,
    IExcelExportService excelExportService) :
    DataServiceController<TDbContext, TEntitySet, TKey>(logger, dataService)
    where TDbContext : DbContext
    where TEntitySet : class, IEntitySet<TKey>, new()
    where TKey : IConvertible
{
    protected readonly IExcelExportService _excelExportService = excelExportService;

    /// <summary>
    /// 返回导出为当前业务数据类型的基础方法
    /// 包含隐式的过滤条件和文件名参数
    /// </summary>
    /// <returns></returns>
    [HttpGet("Export")]
    public virtual async Task<IActionResult> ExportAsync() => await _excelExportService.ExportAsync(await ExportAsync<TEntitySet>());

    /// <summary>
    /// 返回导出为当前业务数据类型的基础方法
    /// </summary>
    /// <typeparam name="TResult">导出的类型</typeparam>
    /// <param name="fileName">导出的文件名</param>
    /// <returns></returns>
    protected virtual async Task<ExcelData<TResult>> ExportAsync<TResult>(string? fileName = default) where TResult : class, IEntitySet<TKey>, new()
    {
        _logger.LogInformation("用户 {userName} 开始导出 {typeName}!", _dataService.UserName, _dataService.TypeName);
        var pagedResult = await Request.GetPagedResultAsync(_dataService.GetQueryable());
        _logger.LogDebug("用户 {userName} 查询到 {typeName} 记录数: " + pagedResult.Total, _dataService.UserName, _dataService.TypeName);
        var result = new ExcelData<TResult>
        {
            FileName = fileName ?? Request.GetRequestOption<string>(nameof(fileName)),
            Columns = Request.GetRequestColumns<TResult>()
        };

        if (pagedResult.Data is not null)
        {
            if (pagedResult.Data is IEnumerable<TResult> data)
            {
                result.Data = data;
            }
            else
            {
                result.Data = pagedResult.Data.CopyTo<IEnumerable<TEntitySet>, IEnumerable<TResult>>();
            }
        }

        return result;
    }
}

/// <summary>
/// 基于 DataService 的数据增删改查带导出数据到 excel 的基础控制器
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
/// <typeparam name="TEntitySet">业务数据类型</typeparam>
[Authorize]
[ApiController]
public abstract class DataExportServiceController<TDbContext, TEntitySet>(
    ILogger<DataExportServiceController<TDbContext, TEntitySet>> logger,
    IDataService<TDbContext, TEntitySet> dataService,
    IExcelExportService excelExportService) :
    DataExportServiceController<TDbContext, TEntitySet, string>(logger, dataService, excelExportService)
    where TDbContext : DbContext
    where TEntitySet : class, IEntitySet, new();